package mspbots.data.sync.logs.service.impl;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import mspbots.data.sync.BaseGenericService;
import mspbots.data.sync.logs.entity.ExceptionLogs;
import mspbots.data.sync.logs.service.ExceptionLogsService;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;

import java.sql.Timestamp;

@Slf4j
@Service
@RequiredArgsConstructor
public class ExceptionLogsServiceImpl extends BaseGenericService implements ExceptionLogsService {


    @Override
    public void save(ExceptionLogs entity) {
        if (ObjectUtils.isEmpty(entity.getSyncId())) {
            log.error("Exception Logs SyncId is null. {}", entity);
            return;
        }
        this.databaseClient.insert().into(ExceptionLogs.class).using(entity).fetch().rowsUpdated().subscribe();
    }

    @Override
    public Flux<ExceptionLogs> selectGrabLog(ExceptionLogs entity) {
        log.debug("selectGrabLog param: {}", entity);
        if (ObjectUtils.isEmpty(entity.getStatus()) && ObjectUtils.isEmpty(entity.getInterfaceName())) {
            return this.databaseClient.execute("SELECT tenant_id,service_name,interface_name,\"sum\"(milliseconds) as milliseconds,date_trunc('day', log_time) as log_time,status\n" +
                    "        FROM exception_logs\n" +
                    "        WHERE log_time BETWEEN :startTime and :endTime" +
                    "        and tenant_id =:tenantId" +
                    "        and service_name =:serviceName" +
                    "        GROUP BY tenant_id,service_name,interface_name,date_trunc('day', log_time),status\n" +
                    "        ORDER BY date_trunc('day', log_time) desc")
                    .as(ExceptionLogs.class)
                    .bind("startTime", Timestamp.valueOf(entity.getStartTime()))
                    .bind("endTime", Timestamp.valueOf(entity.getEndTime()))
                    .bind("tenantId", entity.getTenantId().longValue())
                    .bind("serviceName", entity.getServiceName())
                    .fetch().all();
        } else if (!ObjectUtils.isEmpty(entity.getStatus()) && ObjectUtils.isEmpty(entity.getInterfaceName())) {
            return this.databaseClient.execute("SELECT tenant_id,service_name,interface_name,\"sum\"(milliseconds) as milliseconds,date_trunc('day', log_time) as log_time,status\n" +
                    "        FROM exception_logs\n" +
                    "        WHERE log_time BETWEEN :startTime and :endTime" +
                    "        and tenant_id =:tenantId" +
                    "        and status =:status" +
                    "        and service_name =:serviceName" +
                    "        GROUP BY tenant_id,service_name,interface_name,date_trunc('day', log_time),status\n" +
                    "        ORDER BY date_trunc('day', log_time) desc")
                    .as(ExceptionLogs.class)
                    .bind("startTime", Timestamp.valueOf(entity.getStartTime()))
                    .bind("endTime", Timestamp.valueOf(entity.getEndTime()))
                    .bind("tenantId", entity.getTenantId().longValue())
                    .bind("status", entity.getStatus())
                    .bind("serviceName", entity.getServiceName())
                    .fetch().all();
        } else if (!ObjectUtils.isEmpty(entity.getStatus()) && !ObjectUtils.isEmpty(entity.getInterfaceName())) {
            return this.databaseClient.execute("SELECT tenant_id,service_name,interface_name,\"sum\"(milliseconds) as milliseconds,date_trunc('day', log_time) as log_time,status\n" +
                    "        FROM exception_logs\n" +
                    "        WHERE log_time BETWEEN :startTime and :endTime" +
                    "        and tenant_id =:tenantId" +
                    "        and status =:status" +
                    "        and service_name =:serviceName" +
                    "        and interface_name =:interfaceName" +
                    "        GROUP BY tenant_id,service_name,interface_name,date_trunc('day', log_time),status\n" +
                    "        ORDER BY date_trunc('day', log_time) desc")
                    .as(ExceptionLogs.class)
                    .bind("startTime", Timestamp.valueOf(entity.getStartTime()))
                    .bind("endTime", Timestamp.valueOf(entity.getEndTime()))
                    .bind("tenantId", entity.getTenantId().longValue())
                    .bind("status", entity.getStatus())
                    .bind("interfaceName", entity.getInterfaceName())
                    .bind("serviceName", entity.getServiceName())
                    .fetch().all();
        } else {
            return this.databaseClient.execute("SELECT tenant_id,service_name,interface_name,\"sum\"(milliseconds) as milliseconds,date_trunc('day', log_time) as log_time,status\n" +
                    "        FROM exception_logs\n" +
                    "        WHERE log_time BETWEEN :startTime and :endTime" +
                    "        and tenant_id =:tenantId" +
                    "        and service_name =:serviceName" +
                    "        and interface_name =:interfaceName" +
                    "        GROUP BY tenant_id,service_name,interface_name,date_trunc('day', log_time),status\n" +
                    "        ORDER BY date_trunc('day', log_time) desc")
                    .as(ExceptionLogs.class)
                    .bind("startTime", Timestamp.valueOf(entity.getStartTime()))
                    .bind("endTime", Timestamp.valueOf(entity.getEndTime()))
                    .bind("tenantId", entity.getTenantId().longValue())
                    .bind("interfaceName", entity.getInterfaceName())
                    .bind("serviceName", entity.getServiceName())
                    .fetch().all();
        }


    }

    @Override
    public Flux<ExceptionLogs> selectGrabLogDetail(ExceptionLogs entity) {
        return this.databaseClient.execute("SELECT * \n" +
                "        FROM exception_logs\n" +
                "        WHERE log_time BETWEEN :startTime and :endTime" +
                "        and tenant_id =:tenantId" +
                "        and status =:status" +
                "        and service_name =:serviceName" +
                "        and interface_name =:interfaceName" +
                "        ORDER BY date_trunc('day', log_time) desc")
                .as(ExceptionLogs.class)
                .bind("startTime", Timestamp.valueOf(entity.getStartTime()))
                .bind("endTime", Timestamp.valueOf(entity.getEndTime()))
                .bind("tenantId", entity.getTenantId().longValue())
                .bind("status", entity.getStatus())
                .bind("interfaceName", entity.getInterfaceName())
                .bind("serviceName", entity.getServiceName())
                .fetch().all();
    }

    @Override
    public Flux<ExceptionLogs> countGrabLogStatus(ExceptionLogs entity) {
        log.debug("countGrabLogStatus param: {}", entity);
        return this.databaseClient.execute("SELECT STATUS,count(STATUS) AS count_status\n" +
                "        FROM exception_logs\n" +
//                "        WHERE log_time BETWEEN :startTime and :endTime" +
                "        where tenant_id =:tenantId" +
                "        and service_name =:serviceName" +
                "        GROUP BY status\n")
                .as(ExceptionLogs.class)
//                .bind("startTime",Timestamp.valueOf(entity.getStartTime()))
//                .bind("endTime", Timestamp.valueOf(entity.getEndTime()))
                .bind("tenantId", entity.getTenantId().longValue())
                .bind("serviceName", entity.getServiceName())
                .fetch().all();
    }


}
